package com.atguigu.gmall.payment.controller;

import com.alipay.api.internal.util.AlipaySignature;
import com.atguigu.gmall.common.result.Result;
import com.atguigu.gmall.model.enums.PaymentType;
import com.atguigu.gmall.model.payment.PaymentInfo;
import com.atguigu.gmall.payment.config.AlipayConfig;
import com.atguigu.gmall.payment.service.AlipayService;
import com.atguigu.gmall.payment.service.PaymentService;
import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
import lombok.RequiredArgsConstructor;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;

import java.util.Map;

/**
 * @author Fxz
 * @version 1.0
 * @date 2022-02-21 19:40
 */
@Slf4j
@Controller
@RequiredArgsConstructor
@RequestMapping("/api/payment/alipay")
public class AlipayController {

	private final AlipayService alipayService;

	private final PaymentService paymentService;

	/**
	 * @ResponseBody 注解直接返回JSON输出到页面
	 */
	@ResponseBody
	@RequestMapping("/submit/{orderId}")
	public String alipay(@PathVariable("orderId") Long orderId) {
		return alipayService.createAliPay(orderId);
	}

	@GetMapping("/callback/return")
	public String callbackReturn() {
		return "redirect:" + AlipayConfig.return_order_url;
	}

	/**
	 * 支付宝异步验签
	 *
	 * @See <a href=https://opendocs.alipay.com/open/270/105902/> 回调url:https:
	 * //商家网站通知地址?voucher_detail_list=[{"amount":"0.20","merchantContribute":"0.00","name":"5折券","otherContribute":"0.20","type":"ALIPAY_DISCOUNT_VOUCHER","voucherId":"2016101200073002586200003BQ4"}]&fund_bill_list=[{"amount":"0.80","fundChannel":"ALIPAYACCOUNT"},{"amount":"0.20","fundChannel":"MDISCOUNT"}]&subject=PC网站支付交易&trade_no=2016101221001004580200203978&gmt_create=2016-10-12
	 * 21:36:12&notify_type=trade_status_sync&total_amount=1.00&out_trade_no=mobile_rdm862016-10-12213600&invoice_amount=0.80&seller_id=2088201909970555&notify_time=2016-10-12
	 * 21:41:23&trade_status=TRADE_SUCCESS&gmt_payment=2016-10-12
	 * 21:37:19&receipt_amount=0.80&passback_params=passback_params123&buyer_id=2088102114562585&app_id=2016092101248425&notify_id=7676a2e1e4e737cff30015c4b7b55e3kh6&
	 * sign_type=RSA2&buyer_pay_amount=0.80&sign=***&point_amount=0.00
	 */
	@SneakyThrows
	@ResponseBody
	@PostMapping("/callback/notify")
	public String callbackNotify(@RequestParam Map<String, String> paramsMap) {
		// 调用SDK验证签名
		boolean signVerified = AlipaySignature.rsaCheckV1(paramsMap, AlipayConfig.alipay_public_key,
				AlipayConfig.charset, AlipayConfig.sign_type);
		String outTradeNo = paramsMap.get("out_trade_no");
		String tradeStatus = paramsMap.get("trade_status");
		PaymentInfo paymentInfo = paymentService.getPaymentInfo(outTradeNo, PaymentType.ALIPAY.name());
		if (signVerified && ObjectUtils.isNotEmpty(paymentInfo)) {
			// 验签成功后，按照支付结果异步通知中的描述，对支付结果中的业务内容进行二次校验，校验成功后在response中返回success并继续商户自身业务处理，校验失败返回failure
			if ("TRADE_SUCCESS".equals(tradeStatus) || "TRADE_FINISHED".equals(tradeStatus)) {
				if (!"PAID".equals(paymentInfo.getPaymentStatus())
						&& !"CLOSED".equals(paymentInfo.getPaymentStatus())) {
					// 更新交易记录状态
					paymentService.paySuccess(outTradeNo, PaymentType.ALIPAY.name(), paramsMap);
					log.info("异步验签成功:{}", paramsMap);
					return "success";
				}
			}
		}
		// 验签失败则记录异常日志，并在response中返回failure.
		return "failure";
	}

	/**
	 * 申请退款
	 */
	@ResponseBody
	@GetMapping("/refund/{orderId}")
	public Result refund(@PathVariable("orderId") Long orderId) {
		boolean flag = alipayService.refund(orderId);
		return Result.ok(flag);
	}

	/**
	 * 关闭交易
	 */
	@GetMapping("/closePay/{orderId}")
	@ResponseBody
	public Boolean closePay(@PathVariable Long orderId) {
		return alipayService.closePay(orderId);
	}

	/**
	 * 查看是否存在交易记录
	 */
	@GetMapping("/checkPayment/{orderId}")
	@ResponseBody
	public Boolean checkPayment(@PathVariable Long orderId) {
		return alipayService.checkPayment(orderId);
	}

	/**
	 * 查询本地是否有交易记录
	 */
	@GetMapping("/getPaymentInfo/{outTradeNo}")
	@ResponseBody
	public PaymentInfo getPaymentInfo(@PathVariable String outTradeNo) {
		return paymentService.getPaymentInfo(outTradeNo, PaymentType.ALIPAY.name());
	}

}
